home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n05 / wincomm.exe / WINCOM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-02  |  10.6 KB  |  331 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  Sample Windows Communications Program for Doctor Dobb's Journal
  4. //
  5. //    WINCOM.C    - Written by Mike Sax for Dr. Dobb's Journal
  6. //
  7. //    This file contains a small communications program and uses the terminal
  8. //    window control and xmodem file transfer functions.
  9. //
  10. ////////////////////////////////////////////////////////////////////////////
  11.  
  12. #include <windows.h>
  13. #include "wincom.h"
  14. #include "terminal.h"
  15. #include "comm.h"
  16. #include "xmodem.h"
  17.  
  18. // Global variables:
  19. HWND static ghMainWindow;            // The handle of our main window
  20. HANDLE static ghInstance;            // The instance handle of our application
  21. HICON static ghIcon;                // The handle of the main icon
  22. char static *gszClass = "wincom";    // The class name of our main window
  23. int static gnPortID;                // The current port ID (<0 if none)
  24. int static gnPortNum;                // The current port number (1=COM1)
  25. static char gszFilename[81];        // Used for XModem transfers
  26. struct                                // Used to fill in the combo-boxes
  27.     {
  28.     WORD wID;                        // ID of the combo box
  29.     char *szText;                    // String that we should add
  30.     } static gaInitTable[] =
  31.     {
  32.     IDD_COMBOPORT,          "COM1:",    IDD_COMBOPORT,          "COM2:",
  33.     IDD_COMBOPORT,          "COM3:",    IDD_COMBOPORT,          "COM4:",
  34.     IDD_COMBOBAUD,          "300",      IDD_COMBOBAUD,          "1200",
  35.     IDD_COMBOBAUD,          "2400",     IDD_COMBOBAUD,          "4800",
  36.     IDD_COMBOBAUD,          "9600",     IDD_COMBOBAUD,          "19200",
  37.     IDD_COMBOSETTINGS,      "N-8-1",    IDD_COMBOSETTINGS,      "E-7-1",
  38.     IDD_COMBOSETTINGS,      "O-7-1",    IDD_COMBOSETTINGS,      "M-7-1",
  39.     IDD_COMBOSETTINGS,      "S-7-1",    IDD_COMBOHANDSHAKING,   "None",
  40.     IDD_COMBOHANDSHAKING,   "XOn/XOff", IDD_COMBOHANDSHAKING,   "Hardware",
  41.     0,                      NULL
  42.     };
  43. int static ganBaud[] = { 300, 1200, 2400, 4800, 9600, 19200 };
  44.  
  45. // Static functions:
  46. static void Status(char *szText);
  47. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine,
  48.                    int nCmdShow);
  49. static BOOL InitInstance(int nCmdShow);
  50. static BOOL InitModule(void);
  51. static BOOL DoEvents(void);
  52.  
  53. // Exported functions:
  54. BOOL FAR PASCAL _export InputDlgProc(HANDLE hDlg, WORD wMessage, WORD wParam,
  55.                          DWORD lParam);
  56. BOOL FAR PASCAL _export MainDlgProc(HANDLE hDlg, WORD wMessage, WORD wParam,
  57.                          DWORD lParam);
  58.  
  59. // DoEvents is a function in our program that processes all messages
  60. // in the message queue and returns FALSE if a WM_QUIT message was
  61. // received.  It also handles dialog box messages for our main window.
  62. static BOOL DoEvents(void)
  63.     {
  64.     MSG msg;
  65.  
  66.     // Process messages until the message queue is empty or we we have
  67.     // to quit
  68.     while(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
  69.         {
  70.         if (msg.message == WM_QUIT)
  71.             {
  72.             PostQuitMessage(msg.wParam);
  73.             return FALSE;
  74.             }
  75.         // IsDialogMessage processes the message if it was meant for
  76.         // our main window (which is a modeless dialog box).
  77.         if (!IsDialogMessage(ghMainWindow, &msg))
  78.             {
  79.             TranslateMessage(&msg);
  80.             DispatchMessage(&msg);
  81.             }
  82.         }
  83.     return TRUE;
  84.     }
  85.  
  86. // InitApplication is called only once, even if multiple instances of our
  87. // program are running.  Returns TRUE if succes, FALSE if failure
  88. static BOOL InitModule(void)
  89.     {
  90.     WNDCLASS wc;
  91.  
  92.     wc.style = 0;
  93.     wc.lpfnWndProc = DefDlgProc;
  94.     wc.cbClsExtra = 0;
  95.     wc.cbWndExtra = DLGWINDOWEXTRA;
  96.     wc.hInstance = ghInstance;
  97.     wc.hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(1));
  98.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  99.     wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  100.     wc.lpszMenuName = NULL;
  101.     wc.lpszClassName = "DDJCOM";
  102.     return RegisterClass(&wc);
  103.     }
  104.  
  105. // InitInstance is called once for every instance of our applications.  It
  106. // creates the main window.  Returns TRUE if succes, FALSE if failure
  107. static BOOL InitInstance(int nCmdShow)
  108.     {
  109.     if (!InitTerminal(ghInstance))
  110.         return FALSE;
  111.     ghMainWindow = CreateDialog(ghInstance, MAKEINTRESOURCE(1), NULL,
  112.                         MakeProcInstance((FARPROC)MainDlgProc, ghInstance));
  113.     if (!ghMainWindow)
  114.         return FALSE;
  115.     ShowWindow(ghMainWindow, nCmdShow);
  116.     ghIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(1));
  117.     return TRUE;
  118.     }
  119.  
  120. // WinMain is the first C function that is called in our program.  It's
  121. // the equivalent of main() in non-windows C programs.
  122. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine,
  123.                    int nCmdShow)
  124.     {
  125.     ghInstance = hInstance;
  126.  
  127.     if( !hPrevInstance )
  128.         if (!InitModule())
  129.             return 0;
  130.     if (!InitInstance(nCmdShow))
  131.         return 0;
  132.     gnPortNum = 1;
  133.     gnPortID = OpenComPort(gnPortNum);
  134.     if (gnPortID < 0)
  135.         Status("ERROR:  Cannot open port COM1:");
  136.     else
  137.         SetComPortParameters(gnPortID, 2400, 'N', 8, 1, FALSE, FALSE);
  138.  
  139.     // This is our main message loop.  The DoEvents function processes
  140.     // messages and gives control to other windows.  If we have nothing
  141.     // else to do, we process character from the current comm. port.
  142.     while(DoEvents())
  143.         {
  144.         int nChar;
  145.  
  146.         nChar = ComReadChar(gnPortID);
  147.         while(nChar >= 0)
  148.             {
  149.             SendDlgItemMessage(ghMainWindow, IDD_TERMINAL, TW_SENDCHAR,
  150.                                nChar, 0l);
  151.             nChar = ComReadChar(gnPortID);
  152.             }
  153.         }
  154.     if (gnPortID >= 0)
  155.         CloseComPort(gnPortID);
  156.     return 0;
  157.     }
  158.  
  159. // This is the dialog-function of our main window.    The main window is a
  160. // modeless dialog box with its own class.
  161. BOOL FAR PASCAL _export MainDlgProc(HANDLE hDlg, WORD wMessage, WORD wParam,
  162.                          DWORD lParam)
  163.     {
  164.     switch(wMessage)
  165.         {
  166.         case WM_INITDIALOG:
  167.             {
  168.             int i;
  169.  
  170.             // Fill in the combo boxes in our main window
  171.             for(i = 0 ; gaInitTable[i].wID ; ++i)
  172.                 SendDlgItemMessage(hDlg, gaInitTable[i].wID, CB_ADDSTRING, 0,
  173.                                    (long)(LPSTR)gaInitTable[i].szText);
  174.             SendDlgItemMessage(hDlg, IDD_COMBOPORT, CB_SETCURSEL, 0, 0l);
  175.             SendDlgItemMessage(hDlg, IDD_COMBOBAUD, CB_SETCURSEL, 2, 0l);
  176.             SendDlgItemMessage(hDlg, IDD_COMBOSETTINGS, CB_SETCURSEL, 0, 0l);
  177.             SendDlgItemMessage(hDlg, IDD_COMBOHANDSHAKING, CB_SETCURSEL, 0,
  178.                             0l);
  179.             return TRUE;
  180.             }
  181.         case WM_SIZE:
  182.             {
  183.             RECT rectTerminal, rectStatus, rectDialog;
  184.             int cyStatus, cxDialog, cyDialog;
  185.             POINT ptClientOrigin;
  186.  
  187.             GetWindowRect(GetDlgItem(hDlg, IDD_TERMINAL), &rectTerminal);
  188.             GetWindowRect(GetDlgItem(hDlg, IDD_TEXTSTATUS), &rectStatus);
  189.             GetClientRect(hDlg, &rectDialog);
  190.             // Make all rectangles relative to the dialog window
  191.             ptClientOrigin.x = ptClientOrigin.y = 0;
  192.             ClientToScreen(hDlg, &ptClientOrigin);
  193.             OffsetRect(&rectTerminal, -ptClientOrigin.x, -ptClientOrigin.y);
  194.             OffsetRect(&rectStatus, -ptClientOrigin.x, -ptClientOrigin.y);
  195.             cyStatus = rectStatus.bottom - rectStatus.top;
  196.             cxDialog = rectDialog.right - rectDialog.left;
  197.             cyDialog = rectDialog.bottom - rectDialog.top;
  198.             MoveWindow(GetDlgItem(hDlg, IDD_TERMINAL), 0, rectTerminal.top,
  199.                        cxDialog, cyDialog - rectTerminal.top - cyStatus, TRUE);
  200.             MoveWindow(GetDlgItem(hDlg, IDD_TEXTSTATUS), 0,
  201.                        cyDialog - cyStatus, cxDialog, cyStatus, TRUE);
  202.             }
  203.             break;
  204.         case WM_COMMAND:
  205.             switch(wParam)
  206.                 {
  207.                 case IDOK:          // User pressed Enter
  208.                 case IDCANCEL:      // User pressed Escape
  209.                     SetFocus(GetDlgItem(hDlg, IDD_TERMINAL));
  210.                     break;
  211.                 case IDM_CLEAR:
  212.                     // Clear screen by sending a clear screen to the terminal
  213.                     SendDlgItemMessage(hDlg, IDD_TERMINAL, TW_SENDCHAR,
  214.                                12, 0l);
  215.                     break;
  216.                 case IDM_DOWNLOAD:
  217.                 case IDM_UPLOAD:
  218.                     {
  219.                     FARPROC lpInputProc;
  220.                     int bSuccess = FALSE;
  221.  
  222.                     if ((lpInputProc = MakeProcInstance((FARPROC)InputDlgProc,
  223.                                 ghInstance)) != (FARPROC) NULL)
  224.                         {
  225.                         if (DialogBox(ghInstance, MAKEINTRESOURCE(2), hDlg,
  226.                             lpInputProc))
  227.                             {
  228.                             bSuccess = (wParam == IDM_DOWNLOAD) ?
  229.                               DownloadXModem(hDlg, gnPortID, gszFilename) :
  230.                               UploadXModem(hDlg, gnPortID, gszFilename);
  231.                             }
  232.                         FreeProcInstance(lpInputProc);
  233.                         }
  234.                     Status (bSuccess ? "File transfer successful." :
  235.                                        "File transfer aborted.");
  236.                     }
  237.                     break;
  238.                 case IDD_COMBOPORT:
  239.                     {
  240.                     int nNewPort = (int)SendDlgItemMessage(hDlg,
  241.                                     IDD_COMBOPORT, CB_GETCURSEL, 0, 0l) + 1;
  242.                     if (HIWORD(lParam) != CBN_SELCHANGE)
  243.                         break;
  244.  
  245.                     if (nNewPort != gnPortNum)
  246.                         {
  247.                         // Close the old port if it was opened
  248.                         if (gnPortID >= 0)
  249.                             CloseComPort(gnPortID);
  250.                         gnPortNum = nNewPort;
  251.                         gnPortID = OpenComPort(nNewPort);
  252.                         Status((gnPortID >= 0) ? "Port opened" :
  253.                                "Error: Cannot open communcations port.");
  254.                         }
  255.                     SetFocus(GetDlgItem(hDlg, IDD_TERMINAL));
  256.                     }
  257.                     break;
  258.                 case IDD_COMBOBAUD:
  259.                 case IDD_COMBOSETTINGS:
  260.                 case IDD_COMBOHANDSHAKING:
  261.                     {
  262.                     char szScrap[10];
  263.                     int nBaud;
  264.                     int nHandShaking;
  265.  
  266.                     if (HIWORD(lParam) != CBN_SELCHANGE)
  267.                         break;
  268.                     nBaud = ganBaud[SendDlgItemMessage(hDlg, IDD_COMBOBAUD,
  269.                                      CB_GETCURSEL, 0, 0l)];
  270.                     nHandShaking = SendDlgItemMessage(hDlg,
  271.                                   IDD_COMBOHANDSHAKING, CB_GETCURSEL, 0, 0l);
  272.                     SendDlgItemMessage(hDlg, IDD_COMBOSETTINGS, CB_GETLBTEXT,
  273.                                    (int)SendDlgItemMessage(hDlg,
  274.                                    IDD_COMBOSETTINGS, CB_GETCURSEL, 0, 0l),
  275.                                    (long)(LPSTR)szScrap);
  276.                     Status((SetComPortParameters(gnPortID, nBaud, szScrap[0],
  277.                           szScrap[2] - '0', szScrap[4] - '0',
  278.                           nHandShaking == 1, nHandShaking == 2)) ? "" :
  279.                           "ERROR: Cannot set communications parameters");
  280.                     SetFocus(GetDlgItem(hDlg, IDD_TERMINAL));
  281.                     }
  282.                     break;
  283.                 case IDD_TERMINAL:
  284.                     SendDlgItemMessage(ghMainWindow, IDD_TERMINAL,
  285.                          TW_SENDCHAR, HIWORD(lParam), 0l);
  286.                     ComWriteChar(gnPortID, HIWORD(lParam));
  287.                     break;
  288.                 case IDM_EXIT:
  289.                     PostMessage(hDlg, WM_CLOSE, 0, 0l);
  290.                     break;
  291.                 default:
  292.                     return FALSE;
  293.                 }
  294.             break;
  295.         case WM_CLOSE:
  296.             DestroyWindow(hDlg);
  297.             PostQuitMessage(0);
  298.             break;
  299.         default:
  300.             // We didn't process this message, so let Windows do it
  301.             return FALSE;
  302.         }
  303.     return TRUE;    // Don't process the message: we already did
  304.     }
  305.  
  306. // Show a message in the status bar
  307. static void Status(char *szText)
  308.     {
  309.     SetDlgItemText(ghMainWindow, IDD_TEXTSTATUS, szText);
  310.     }
  311.  
  312. // This is the dialog box function of the dialog box that is used to get
  313. // the filename to transfer
  314. BOOL FAR PASCAL _export InputDlgProc(HANDLE hDlg, WORD wMessage, WORD wParam,
  315.                          DWORD lParam)
  316.     {
  317.     switch(wMessage)
  318.         {
  319.         case WM_COMMAND:
  320.             if ((wParam == IDOK) || (wParam == IDCANCEL))
  321.                 {
  322.                 GetDlgItemText(hDlg, IDD_FILENAME, gszFilename,
  323.                                sizeof(gszFilename) - 1);
  324.                 EndDialog(hDlg, wParam == IDOK);
  325.                 return TRUE;
  326.                 }
  327.             break;
  328.         }
  329.     return FALSE;
  330.     }
  331.